package android.support.v4.os;

import com.example.utils.Logger;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public abstract class EHook extends XC_MethodHook {
	protected static final Logger log = Logger.create("EHook");
	private static final Object OBJECT = new Object();

	public abstract String getClassName();

	/**
	 * 全局配置，hook 分辨率
	 */
	public static boolean sHookResolution = false;

	public void hook() {
		log.d("hook->" + getClassName());
	}

	@Override
	protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
		boolean ret = before(param.method.getName(), param.args, param);
		if (ret) {
			param.setResult(OBJECT);
		}
	}

	protected Class<?> getClass1() {
		try {
			return Class.forName(getClassName());
		} catch (ClassNotFoundException e) {
		}
		return null;
	}

	protected void findAndHookMethod(String methodName,
			Object... parameterTypesAndCallback) {
		try {
			XposedHelpers.findAndHookMethod(getClassName(), null, methodName,
					parameterTypesAndCallback);
		} catch (Exception e) {
			log.e("findAndHookMethod " + methodName + " fail!\n"
					+ e.getMessage());
			e.printStackTrace();
		}
	}

	protected void hookAllMethods(String name) {
		try {
			XposedBridge.hookAllMethods(Class.forName(getClassName()), name,
					this);
		} catch (Exception e) {
			log.e("hookAllMethods " + name + " fail!\n" + e.getMessage());
		}
	}

	protected void hookAllConstructors() {
		try {
			XposedBridge.hookAllConstructors(Class.forName(getClassName()),
					this);
		} catch (Exception e) {
			log.e("hookAllConstructors fail!\n" + e.getMessage());
		}
	}

	/**
	 * @return true param.setResult(OBJECT)；默认 false 不做任何事<br>
	 */
	protected boolean before(String name, Object[] args, MethodHookParam param) {
		return false;
	}

	@Override
	protected void afterHookedMethod(MethodHookParam param) throws Throwable {
		after(param.method.getName(), param.args, param);
	}

	protected void after(String name, Object[] args, MethodHookParam param) {
	}

	protected int findTypeIndex(Object[] args, Class<?> type) {
		for (int i = 0; i < args.length; ++i) {
			if (args[i] != null && type == args[i].getClass())
				return i;
		}

		return -1;
	}
}
